library(tidyverse)
library(lubridate)
library(plotly)
library(ggrepel)
countries = c("Austria", "Belgium", "Czechia", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Iceland", "Ireland", "Italy", "Latvia", "Luxembourg", "Netherlands", "Norway", "Poland", "Portugal", "Slovakia", "Slovenia", "Spain", "Sweden", "Switzerland", "United Kingdom", "Canada", "Chile", "Mexico", "Australia", "Japan", "New Zealand", "Israel", "Turkey", "US", "South Korea", "China", "Taiwan*")
df <- read_csv("covid_19_clean_complete.csv")
Parsed with column specification:
cols(
`Province/State` = [31mcol_character()[39m,
`Country/Region` = [31mcol_character()[39m,
Lat = [32mcol_double()[39m,
Long = [32mcol_double()[39m,
Date = [31mcol_character()[39m,
Confirmed = [32mcol_double()[39m,
Deaths = [32mcol_double()[39m,
Recovered = [32mcol_double()[39m
)
pop <- read.csv("API_SP.POP.TOTL_DS2_en_csv_v2_936048.csv")
pop <- tibble(country = pop$Country.Name, pop = pop$X2018)
tests <- read_csv("full-list-covid-19-tests-per-day.csv") %>%
mutate(tests = `Daily change in cumulative total tests`)
Parsed with column specification:
cols(
Entity = [31mcol_character()[39m,
Code = [31mcol_character()[39m,
Date = [31mcol_character()[39m,
`Daily change in cumulative total tests` = [32mcol_double()[39m
)
options(scipen=999)
covid <- df %>%
mutate(Date = mdy(Date)) %>%
group_by(`Country/Region`, Date) %>%
summarise(Confirmed = sum(Confirmed, na.rm = T),
Deaths = sum(Deaths, na.rm = T),
Recovered = sum(Recovered, na.rm = T)) %>%
arrange(`Country/Region`, Date)
final <- covid %>%
group_by(`Country/Region`) %>%
filter(Confirmed >= 100) %>%
mutate(hunfirst = if_else( Date == min(Date), 1, 0),
days_since_hun = row_number(),
marginal_confirmed = Confirmed - lag(Confirmed)) %>%
left_join( pop %>%
mutate(country = case_when(
country == "United States" ~ "US",
country == "Korea, Rep." ~ "South Korea",
TRUE ~ as.character(country))),
by = c("Country/Region" = "country")) %>%
drop_na() %>%
mutate(confirmed_permil = Confirmed/pop*1000000,
deaths_permil = Deaths/pop*1000000,
marginal_confirmed_permil = confirmed_permil - lag(confirmed_permil)) %>%
left_join(tests %>%
mutate(Date = mdy(Date),
Entity = if_else(Entity == "United States", "US", Entity)) %>%
select(Entity, Date, tests), by = c("Country/Region" = "Entity", "Date"))
final <- final %>%
left_join(final %>%
filter(confirmed_permil >= 20) %>%
group_by(`Country/Region`) %>%
mutate(days_sinc_twcon = row_number())) %>%
left_join(final %>%
filter(deaths_permil >= 3) %>%
group_by(`Country/Region`) %>%
mutate(days_sinc_threed = row_number()))
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
write_csv(final, "covid_final.csv")
graph_confirmed <- final %>%
filter(`Country/Region` %in% countries,
days_since_hun < 60) %>%
ggplot(aes(x = days_since_hun, y = Confirmed, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
last <- final %>%
filter(`Country/Region` %in% countries,
days_since_hun < 60) %>%
group_by(`Country/Region`) %>%
filter(days_since_hun == max(days_since_hun))
graph <- graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = Confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Confirmed cases by days since 100th case", x = "", y = "")
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
NA
graph_confirmed <- final %>%
filter(`Country/Region` %in% countries,
days_since_hun < 60) %>%
ggplot(aes(x = days_since_hun, y = marginal_confirmed, color = `Country/Region`)) +
geom_smooth(se=F) + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Marginal confirmed cases by days since 100th case", x = "", y = "")
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 22 rows containing non-finite values (stat_smooth).
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
graph_confirmed <- final %>%
filter(`Country/Region` %in% countries,
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_twcon, y = confirmed_permil, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_sinc_twcon + 2, y = confirmed_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Confirmed per 1M by days since 20th case per 1M", x = "", y = "")
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
NA
graph_confirmed <- final %>%
filter(`Country/Region` %in% countries,
days_since_hun < 60,
!is.na(tests)) %>%
ggplot(aes(x = days_since_hun, y = marginal_confirmed/tests, color = `Country/Region`)) +
geom_smooth(se = F) + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed/tests, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "% of tests confirmed by days since 100th confirmed", x = "", y = "")
plotly <- plotly_build(graph)
plotly$height <- 900
plotly$width <- 1200
plotly$sizingPolicy$defaultWidth <- 1200
plotly$sizingPolicy$defaultHeight <- 900
plotly
graph_confirmed <- final %>%
filter(`Country/Region` %in% countries,
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_threed, y = deaths_permil, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
graph <- graph_confirmed +
geom_text(aes(x = days_sinc_threed + 2, y = deaths_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Deaths per 1M by days since 3rd death per 1M", x = "", y = "")
plotly <- plotly_build(graph)
Transformation introduced infinite values in continuous y-axis
plotly$height <- 900
plotly$width <- 1100
plotly$sizingPolicy$defaultWidth <- 1100
plotly$sizingPolicy$defaultHeight <- 900
plotly
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQotLS0KdGl0bGU6ICJSIE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGdncmVwZWwpCmNvdW50cmllcyA9IGMoIkF1c3RyaWEiLCAiQmVsZ2l1bSIsICJDemVjaGlhIiwgIkRlbm1hcmsiLCAiRXN0b25pYSIsICJGaW5sYW5kIiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkdyZWVjZSIsICJIdW5nYXJ5IiwgIkljZWxhbmQiLCAiSXJlbGFuZCIsICJJdGFseSIsICJMYXR2aWEiLCAiTHV4ZW1ib3VyZyIsICJOZXRoZXJsYW5kcyIsICJOb3J3YXkiLCAiUG9sYW5kIiwgIlBvcnR1Z2FsIiwgIlNsb3Zha2lhIiwgIlNsb3ZlbmlhIiwgIlNwYWluIiwgIlN3ZWRlbiIsICJTd2l0emVybGFuZCIsICJVbml0ZWQgS2luZ2RvbSIsICJDYW5hZGEiLCAiQ2hpbGUiLCAiTWV4aWNvIiwgIkF1c3RyYWxpYSIsICJKYXBhbiIsICJOZXcgWmVhbGFuZCIsICJJc3JhZWwiLCAiVHVya2V5IiwgIlVTIiwgIlNvdXRoIEtvcmVhIiwgIkNoaW5hIiwgIlRhaXdhbioiKQpkZiA8LSByZWFkX2NzdigiY292aWRfMTlfY2xlYW5fY29tcGxldGUuY3N2IikKcG9wIDwtIHJlYWQuY3N2KCJBUElfU1AuUE9QLlRPVExfRFMyX2VuX2Nzdl92Ml85MzYwNDguY3N2IikKcG9wIDwtIHRpYmJsZShjb3VudHJ5ID0gcG9wJENvdW50cnkuTmFtZSwgcG9wID0gcG9wJFgyMDE4KQp0ZXN0cyA8LSByZWFkX2NzdigiZnVsbC1saXN0LWNvdmlkLTE5LXRlc3RzLXBlci1kYXkuY3N2IikgJT4lCiAgbXV0YXRlKHRlc3RzID0gYERhaWx5IGNoYW5nZSBpbiBjdW11bGF0aXZlIHRvdGFsIHRlc3RzYCkKb3B0aW9ucyhzY2lwZW49OTk5KQpgYGAKCgpgYGB7cn0KY292aWQgPC0gZGYgJT4lCiAgbXV0YXRlKERhdGUgPSBtZHkoRGF0ZSkpICU+JQogIGdyb3VwX2J5KGBDb3VudHJ5L1JlZ2lvbmAsIERhdGUpICU+JQogIHN1bW1hcmlzZShDb25maXJtZWQgPSBzdW0oQ29uZmlybWVkLCBuYS5ybSA9IFQpLAogICAgICAgICAgICBEZWF0aHMgPSBzdW0oRGVhdGhzLCBuYS5ybSA9IFQpLAogICAgICAgICAgICBSZWNvdmVyZWQgPSBzdW0oUmVjb3ZlcmVkLCBuYS5ybSA9IFQpKSAlPiUKICBhcnJhbmdlKGBDb3VudHJ5L1JlZ2lvbmAsIERhdGUpCgoKZmluYWwgPC0gY292aWQgJT4lCiAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgZmlsdGVyKENvbmZpcm1lZCA+PSAxMDApICU+JQogIG11dGF0ZShodW5maXJzdCA9IGlmX2Vsc2UoIERhdGUgPT0gbWluKERhdGUpLCAxLCAwKSwKICAgICAgICAgZGF5c19zaW5jZV9odW4gPSByb3dfbnVtYmVyKCksCiAgICAgICAgIG1hcmdpbmFsX2NvbmZpcm1lZCA9IENvbmZpcm1lZCAtIGxhZyhDb25maXJtZWQpKSAlPiUKICBsZWZ0X2pvaW4oIHBvcCAlPiUKICAgICAgICAgICAgICAgbXV0YXRlKGNvdW50cnkgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgY291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIgfiAiVVMiLAogICAgICAgICAgICAgICAgIGNvdW50cnkgPT0gIktvcmVhLCBSZXAuIiB+ICJTb3V0aCBLb3JlYSIsCiAgICAgICAgICAgICAgICAgVFJVRSB+IGFzLmNoYXJhY3Rlcihjb3VudHJ5KSkpLCAKICAgICAgICAgICAgIGJ5ID0gYygiQ291bnRyeS9SZWdpb24iID0gImNvdW50cnkiKSkgJT4lCiAgZHJvcF9uYSgpICU+JQogIG11dGF0ZShjb25maXJtZWRfcGVybWlsID0gQ29uZmlybWVkL3BvcCoxMDAwMDAwLAogICAgICAgICBkZWF0aHNfcGVybWlsID0gRGVhdGhzL3BvcCoxMDAwMDAwLAogICAgICAgICBtYXJnaW5hbF9jb25maXJtZWRfcGVybWlsID0gY29uZmlybWVkX3Blcm1pbCAtIGxhZyhjb25maXJtZWRfcGVybWlsKSkgJT4lCiAgbGVmdF9qb2luKHRlc3RzICU+JQogICAgICAgICAgICAgIG11dGF0ZShEYXRlID0gbWR5KERhdGUpLAogICAgICAgICAgICAgICAgICAgICBFbnRpdHkgPSBpZl9lbHNlKEVudGl0eSA9PSAiVW5pdGVkIFN0YXRlcyIsICJVUyIsIEVudGl0eSkpICU+JQogICAgICAgICAgICAgIHNlbGVjdChFbnRpdHksIERhdGUsIHRlc3RzKSwgYnkgPSBjKCJDb3VudHJ5L1JlZ2lvbiIgPSAiRW50aXR5IiwgIkRhdGUiKSkKCgpmaW5hbCA8LSBmaW5hbCAlPiUKICBsZWZ0X2pvaW4oZmluYWwgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKGNvbmZpcm1lZF9wZXJtaWwgPj0gMjApICU+JQogICAgICAgICAgICAgIGdyb3VwX2J5KGBDb3VudHJ5L1JlZ2lvbmApICU+JQogICAgICAgICAgICAgIG11dGF0ZShkYXlzX3NpbmNfdHdjb24gPSByb3dfbnVtYmVyKCkpKSAlPiUKICBsZWZ0X2pvaW4oZmluYWwgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKGRlYXRoc19wZXJtaWwgPj0gMykgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKGRheXNfc2luY190aHJlZWQgPSByb3dfbnVtYmVyKCkpKQoKd3JpdGVfY3N2KGZpbmFsLCAiY292aWRfZmluYWwuY3N2IikKICAKCmBgYAoKCgoKCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA8LSBmaW5hbCAlPiUKICBmaWx0ZXIoYENvdW50cnkvUmVnaW9uYCAlaW4lIGNvdW50cmllcywKICAgICAgICAgZGF5c19zaW5jZV9odW4gPCA2MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5c19zaW5jZV9odW4sIHkgPSBDb25maXJtZWQsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCkpICsgCiAgZ2VvbV9saW5lKCkgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgpsYXN0IDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgY291bnRyaWVzLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUKICBmaWx0ZXIoZGF5c19zaW5jZV9odW4gPT0gbWF4KGRheXNfc2luY2VfaHVuKSkKCmdyYXBoIDwtIGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY2VfaHVuICsgMiwgeSA9IENvbmZpcm1lZCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gLCBsYWJlbCA9IGBDb3VudHJ5L1JlZ2lvbmApLCBkYXRhID0gbGFzdCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJDb25maXJtZWQgY2FzZXMgYnkgZGF5cyBzaW5jZSAxMDB0aCBjYXNlIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQogCmBgYAoKCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA8LSBmaW5hbCAlPiUKICBmaWx0ZXIoYENvdW50cnkvUmVnaW9uYCAlaW4lIGNvdW50cmllcywKICAgICAgICAgZGF5c19zaW5jZV9odW4gPCA2MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5c19zaW5jZV9odW4sIHkgPSBtYXJnaW5hbF9jb25maXJtZWQsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCkpICsgCiAgZ2VvbV9zbW9vdGgoc2U9RikgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgoKZ3JhcGggPC0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jZV9odW4gKyAyLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJNYXJnaW5hbCBjb25maXJtZWQgY2FzZXMgYnkgZGF5cyBzaW5jZSAxMDB0aCBjYXNlIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQpgYGAKCgoKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgY291bnRyaWVzLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNfdHdjb24sIHkgPSBjb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fbGluZSgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgdGhlbWVfbWluaW1hbCgpIAogIAoKCmdyYXBoIDwtIGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY190d2NvbiArIDIsIHkgPSBjb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJDb25maXJtZWQgcGVyIDFNICBieSBkYXlzIHNpbmNlIDIwdGggY2FzZSBwZXIgMU0iLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPC0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0IDwtIDkwMApwbG90bHkkd2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA8LSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA8LSA5MDAKcGxvdGx5CiAKYGBgCgoKCgoKCgoKCgpgYGB7ciBldmFsPUZBTFNFfQpncmFwaF9jb25maXJtZWQgPC0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjb3VudHJpZXMsCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjAsCiAgICAgICAgICFpcy5uYSh0ZXN0cykpICU+JQogIGdncGxvdChhZXMoeCA9IGRheXNfc2luY2VfaHVuLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkL3Rlc3RzLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fc21vb3RoKHNlID0gRikgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgoKZ3JhcGggPC0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jZV9odW4gKyAyLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkL3Rlc3RzLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICIlIG9mIHRlc3RzIGNvbmZpcm1lZCBieSBkYXlzIHNpbmNlIDEwMHRoIGNvbmZpcm1lZCIsIHggPSAiIiwgeSA9ICIiKQoKCiAgCiAgCnBsb3RseSA8LSBwbG90bHlfYnVpbGQoZ3JhcGgpCnBsb3RseSRoZWlnaHQgPC0gOTAwCnBsb3RseSR3aWR0aCA8LSAxMjAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdFdpZHRoIDwtIDEyMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0SGVpZ2h0IDwtIDkwMApwbG90bHkKYGBgCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkIDwtIGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgY291bnRyaWVzLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNfdGhyZWVkLCB5ID0gZGVhdGhzX3Blcm1pbCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gKSkgKyAKICBnZW9tX2xpbmUoKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCgpncmFwaCA8LSBncmFwaF9jb25maXJtZWQgKyAKICBnZW9tX3RleHQoYWVzKHggPSBkYXlzX3NpbmNfdGhyZWVkICsgMiwgeSA9IGRlYXRoc19wZXJtaWwsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIkRlYXRocyBwZXIgMU0gYnkgZGF5cyBzaW5jZSAzcmQgZGVhdGggcGVyIDFNIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5IDwtIHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA8LSA5MDAKcGxvdGx5JHdpZHRoIDwtIDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPC0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPC0gOTAwCnBsb3RseQpgYGAKCgoKCgoKCgoKCgoKCgoKCgo=